﻿using ArtMath.Attribute;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Flag;
using ArtMath.Helper;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;

namespace ArtMath.Component.Polygon
{
    /// <summary>
    /// 等腰梯形
    /// </summary>
    [Serializable]
    public class IsoscelesTrapezoid : TrapezoidBase
    {
        public IsoscelesTrapezoid(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.dytx, addToList)
        {
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}1", "Waist")]
        public override LineSegmentBase Waist1
        {
            get
            {
                return base.Waist1;
            }

            set
            {
                base.Waist1 = value;
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}2", "Waist")]
        public override LineSegmentBase Waist2
        {
            get
            {
                return base.Waist2;
            }

            set
            {
                base.Waist2 = value;
            }
        }
        public override int ClickTimes
        {
            get
            {
                return 3;
            }
        }
        public override void ComponentBuilding(Base component)
        {
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
            if (OrderIndex == 0)
            {
                if (component == Hemline1)
                {
                    PointD w2 = Pad.PxyToXY(Hemline1.SpareCoordinate),
                        h2 = Waist1.Point1.ToPointD().GetMirrorPoint((Hemline1.Point1.ToPointD() + w2) / 2, -1 / Hemline1.Slope);
                    SpareCoordinate = Pad.XYToPxy(h2);
                    double db2len = h2.DistanceTo(Waist1.Point1.ToPointD());
                    Circumference = Waist1.Length * 2 + Hemline1.Length + db2len;
                    Area = Math.Abs((db2len + Hemline1.Length) * Math.Sqrt((db2len + Waist1.Length * 2 - Hemline1.Length) * (db2len - Hemline1.Length) * (db2len - Hemline1.Length) * (Waist1.Length * 2 - db2len + Hemline1.Length)) / 4 / (db2len - Hemline1.Length));
                    BaryCenter = Utility.GetBaryCenter(new PointD[] { Waist1.Point1.ToPointD(), Hemline1.Point1.ToPointD(), w2, h2 });
                }
                else
                {
                    return;
                }
            }
            else
            {
                if (component == Waist1)
                {
                    PointD h2 = Pad.PxyToXY(Waist1.SpareCoordinate),
                        w2 = h2.GetMirrorPoint((Hemline1.Point1.ToPointD() + Waist1.Point1.ToPointD()) / 2, -1 / Hemline1.Slope);
                    SpareCoordinate = Pad.XYToPxy(w2);
                    double db2len = h2.DistanceTo(w2);
                    Circumference = Waist1.Length * 2 + Hemline1.Length + db2len;
                    Area = Math.Abs((db2len + Hemline1.Length) * Math.Sqrt((db2len + Waist1.Length * 2 - Hemline1.Length) * (db2len - Hemline1.Length) * (db2len - Hemline1.Length) * (Waist1.Length * 2 - db2len + Hemline1.Length)) / 4 / (db2len - Hemline1.Length));
                    BaryCenter = Utility.GetBaryCenter(new PointD[] { Hemline1.Point1.ToPointD(), Waist1.Point1.ToPointD(), h2, w2 });
                }
                else
                {
                    return;
                }
            }
            base.ComponentBuilding(component);
        }
        public override PointCollectionBase[] GetInPointMovingRange(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 1:
                    LineSegmentBase hemline = null;
                    PointD mirror = PointD.Empty;
                    if (movePoint == Waist1.Point1)
                    {
                        if (OrderIndex == 0)
                        {
                            hemline = Hemline1;
                            mirror = Hemline2.Point1.NewXY;
                        }
                        else
                        {
                            hemline = Hemline2;
                            mirror = Hemline1.Point1.NewXY;
                        }
                    }
                    else if (movePoint == Waist2.Point1)
                    {
                        if (OrderIndex == 0)
                        {
                            hemline = Hemline2;
                            mirror = Hemline1.Point1.NewXY;
                        }
                        else
                        {
                            hemline = Hemline1;
                            mirror = Hemline2.Point1.NewXY;
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        hemline = Hemline2;
                        if (OrderIndex == 0)
                        {
                            mirror = Waist2.Point1.NewXY;
                        }
                        else
                        {
                            mirror = Waist1.Point1.NewXY;
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        hemline = Hemline1;
                        if (OrderIndex == 0)
                        {
                            mirror = Waist1.Point1.NewXY;
                        }
                        else
                        {
                            mirror = Waist2.Point1.NewXY;
                        }
                    }
                    return new PointCollectionBase[] { new DiscontinuityPoint(mirror.GetMirrorPoint(hemline.NewMidPoint, -1 / hemline.NewSlope)) };
                case 2:
                    if (movePoint == Waist2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            PointD center = (OrderIndex == 0 ? Hemline2 : Hemline1).Point1.NewXY;
                            return new PointCollectionBase[] { new InCircle(center, center.DistanceTo((OrderIndex == 0 ? Hemline1 : Hemline2).Point1.NewXY)) };
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope, Hemline2.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist1.Point1.NewXY, Waist1.NewLength) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist1.Point1.NewXY, Waist1.NewLength) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope, Hemline1.Point1.NewXY) };
                            }
                        }
                    }
                    else if (movePoint == Waist1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            PointD center = (OrderIndex == 0 ? Hemline1 : Hemline2).Point1.NewXY;
                            return new PointCollectionBase[] { new InCircle(center, center.DistanceTo((OrderIndex == 0 ? Hemline2 : Hemline1).Point1.NewXY)) };
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.Point1.NewXY, Waist2.NewLength) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope, Hemline2.Point1.NewXY) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope, Hemline1.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.Point1.NewXY, Waist2.NewLength) };
                            }
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope, Waist1.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Hemline2.Point1.NewXY, Waist1.NewLength) };
                            }
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new OutCircle(Hemline2.Point1.NewXY, Waist2.NewLength) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope, Waist2.Point1.NewXY) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            PointD center = (OrderIndex == 0 ? Waist1 : Waist2).Point1.NewXY;
                            return new PointCollectionBase[] { new InCircle(center, center.DistanceTo((OrderIndex == 0 ? Waist2 : Waist1).Point1.NewXY)) };
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new OutCircle(Hemline1.Point1.NewXY, Waist1.NewLength) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope, Waist1.Point1.NewXY) };
                            }
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope, Waist2.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Hemline1.Point1.NewXY, Waist2.NewLength) };
                            }
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            PointD center = (OrderIndex == 0 ? Waist2 : Waist1).Point1.NewXY;
                            return new PointCollectionBase[] { new InCircle(center, center.DistanceTo((OrderIndex == 0 ? Waist1 : Waist2).Point1.NewXY)) };
                        }
                    }
                    break;
            }
            return base.GetInPointMovingRange(movePoint, sender);
        }
        public override void InternalPointMove(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 2:
                    PointD tmp;
                    if (movePoint == Waist2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Hemline2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : Hemline1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? movePoint.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : Waist1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline1.Point1.Move(tmp, true);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Waist1.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : Waist2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline2.Point1.Move(tmp, true);
                        }
                    }
                    else if (movePoint == Waist1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Hemline1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : Hemline2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist2.Point1.Move(tmp, true);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Waist2.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : movePoint.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline1.Point1.Move(tmp, true);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? movePoint.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : Waist2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline2.Point1.Move(tmp, true);
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? movePoint.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : Hemline2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist2.Point1.Move(tmp, true);
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Hemline2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : movePoint.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Waist1.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : Waist2.Point1.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline2.Point1.Move(tmp, true);
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Hemline1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : movePoint.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist2.Point1.Move(tmp, true);
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? movePoint.NewXY.GetMirrorPoint(Hemline1.NewMidPoint, -1 / Hemline1.NewSlope) : Hemline1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            tmp = OrderIndex == 0 ? Waist2.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope) : Waist1.Point1.NewXY.GetMirrorPoint(Hemline2.NewMidPoint, -1 / Hemline2.NewSlope);
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline1.Point1.Move(tmp, true);
                        }
                    }
                    return;
            }
            base.InternalPointMove(movePoint, sender);
        }
        public override bool CanDrawVirtual
        {
            get
            {
                if (OrderIndex == 0)
                {
                    return Hemline1 != null;
                }
                else
                {
                    return Waist1 != null;
                }
            }
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            if (CanDrawVirtual)
            {
                if (OrderIndex == 0)
                {
                    gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Waist1.Point1.Pxy.ToPointF(), Hemline1.Point1.Pxy.ToPointF(), Hemline1.SpareCoordinate_.ToPointF(), SpareCoordinate_.ToPointF() });
                    gra.DrawLineSegment(Hemline1.SpareCoordinate_, SpareCoordinate_);
                    gra.DrawLineSegment(SpareCoordinate_, Waist1.Point1.Pxy);
                    gra.DrawPoint(SpareCoordinate_);
                }
                else
                {
                    gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Hemline1.Point1.Pxy.ToPointF(), Waist1.Point1.Pxy.ToPointF(), Waist1.SpareCoordinate_.ToPointF(), SpareCoordinate_.ToPointF() });
                    gra.DrawLineSegment(Waist1.SpareCoordinate_, SpareCoordinate_);
                    gra.DrawLineSegment(SpareCoordinate_, Hemline1.Point1.Pxy);
                    gra.DrawPoint(SpareCoordinate_);
                }
            }
        }
        protected override void ClickOrder(IList<PointCreatingArgs> args, int clickTimes, Predicate<PointCreatingArgs> act)
        {
            if (act == null) return;
            if (OrderIndex == 1)
            {
                if (!act(args[1])) return;
                if (!act(args[0])) return;
                if (!act(args[3])) return;
                if (!act(args[2])) return;
                return;
            }
            base.ClickOrder(args, clickTimes, act);
        }
        public override void CreateComponents()
        {
            if (OrderIndex == 0)
            {
                if (Waist1 == null)
                {
                    Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                    Waist1.CreateComponents($"{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("Waist")}2");
                }
                else if (Hemline1 == null)
                {
                    Waist1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("Waist")}2");
                    Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false);
                    Hemline1.CreateComponents(Waist1.Point2);
                }
                else
                {
                    Hemline1.CreateComponents($"{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("Waist")}2", new PointCollectionBase[] { new OutCircle(Waist1.Point1.ToPointD(), Waist1.Length) });
                    Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}2", false);
                    Waist2.CreateComponents(Hemline1.Point2);
                    Flags.ShieldCtrl(() => { Waist2.CreateComponents(Pad.CreatePoint($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("Waist")}2", SpareCoordinate, false)); });
                    Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                    Hemline2.CreateComponents(Waist2.Point2, Waist1.Point1);
                    base.CreateComponents();
                }
            }
            else
            {
                if (Hemline1 == null)
                {
                    Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                    Hemline1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("Waist")}2");
                }
                else if (Waist1 == null)
                {
                    Hemline1.CreateComponents($"{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("Waist")}2");
                    Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}1", false);
                    Waist1.CreateComponents(Hemline1.Point2);
                }
                else
                {
                    Waist1.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Waist")}1{Resources.Join}{Resources.Translate("Waist")}2", new PointCollectionBase[] {new CustomCollection((PointD pt) =>
                    {
                        return pt.GetProjectivePoint(Hemline1.MidPoint, -1 / Hemline1.Slope);
                    },
                    (PointD pt) => 
                    {
                        return Utility.OnSameSide(Hemline1.MidPoint, -1 / Hemline1.Slope, pt, Waist1.Point1.ToPointD());
                    }) });
                    Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                    Hemline2.CreateComponents(Waist1.Point2);
                    Flags.ShieldCtrl(() => { Hemline2.CreateComponents(Pad.CreatePoint($"{Resources.Translate("Waist")}2{Resources.Join}{Resources.Translate("Waist")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("Waist")}2", SpareCoordinate, false)); });
                    Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Waist")}2", false);
                    Waist2.CreateComponents(Hemline2.Point2, Hemline1.Point1);
                    base.CreateComponents();
                }
            }
        }
    }
}
